// Copyright (c) [Year] [name of copyright holder]
// [Software Name] is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2. 
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2 
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
// See the Mulan PSL v2 for more details.

/*!
 * \autor captainpeng
 * \date 2019-3-5
 * \update 2019-3-6
 * \version 1.0
 * \copyright
 */

#ifndef MY_MEMORY_HPP
#define MY_MEMORY_HPP

#include<cstdlib>
#include"memory/memMan.hpp"
#include"memory/memFunc.hpp"

#include"mystd.hpp"

namespace my{
    // 2020-4-6 删除了标志，用上了分配栈
    // 分配栈的概念挺不错的，但是 c++ 上面能实现还是有限，只能以浪费性能来实现内存栈
    struct allocstack{
    private:
        void * top;
        friend class memory;

    public:
        allocstack():top(nullptr){}
        ~allocstack();
        void free();
    };


    // 2019-12-17
	// 旧的内存管理器，主权 ＋ 计数器，由于计数器已经够用了，也就不适用主权了。
    // 同时与 shareMemory 比较，新的管理器使用平衡二叉树，可以更快速获得信息。

    // 2019-12-25
    // 将该内存管理进行改造，改造成一个通用的内存管理器，只用我们自己的 memMan
    class memory{
    public:
        using manType = memMan;
        using treeType = typename manType::treeType;
        using nodePtr = typename manType::treeNodePtr;
        memory() = delete;

    private:
        inline static void PlusCount(nodePtr np){
			if(np != nullptr){
                np->plusCount();
			}
        }
        
        inline static void MinusCount(nodePtr np){
            if(np != nullptr){
                np->minusCount();
                if(np->mCount == 0){
                    manType::GetTree().erase(np->mValue);
                }
            }
        }
        
    public:
        // 分配内存，这里参数用的是指针的指针
        // Alloc 表示该内存分配和 c 语言的原生 alloc 一样，只负责分配，不负责删除，需要的话你得自己来释放内存
        template<typename T>
        static T * alloc(size_t size, memAllocFunc allocFunc = memFunc<T>::Alloc, memFreeFunc freeFunc = memFunc<T>::Free){
            if(size == 0) return nil<T>();
            return static_cast<T *>(manType::GetTree().insert(nullptr, size, sizeof(T), 0, allocFunc, freeFunc));
        }

        // Alloc 测试版本，输入函数或者 lambda 表达始作为函数调用后的 callback
        template<typename T, typename C1, typename C2>
        static T * alloc(size_t size, const C1 & call_back1, const C2 & call_back2){
            if(size == 0) return nil<T>();
            using fn = memDebugFunc<T, C1, C2>;
            fn::C1() = &call_back1;
            fn::C2() = &call_back2;
            return static_cast<T *>(manType::GetTree().insert(nullptr, size, sizeof(T), 0, fn::Alloc, fn::Free));
        }

        // Count Alloc 表示该内存为计数器来分配内存，内存一分配，则其计数器则为 1
        template<typename T>
        static T * calloc(size_t size, memAllocFunc allocFunc = memFunc<T>::Alloc, memFreeFunc freeFunc = memFunc<T>::Free){
            if(size == 0) return nil<T>();
            return static_cast<T *>(manType::GetTree().insert(nullptr, size, sizeof(T), 1, allocFunc, freeFunc));
        }

        // Count Alloc 测试版本，输入函数或者 lambda 表达始作为函数调用后的 callback
        template<typename T, typename C1, typename C2>
        static T * calloc(size_t size, const C1 & call_back1, const C2 & call_back2){
            if(size == 0) return nil<T>();
            using fn = memDebugFunc<T, C1, C2>;
            fn::C1() = &call_back1;
            fn::C2() = &call_back2;
            return static_cast<T *>(manType::GetTree().insert(nullptr, size, sizeof(T), 1, fn::Alloc, fn::Free));
        }

        // Stack Alloc 内存栈分配
        template<typename T>
        static T * salloc(allocstack & stack, size_t size, memAllocFunc allocFunc = memFunc<T>::Alloc, memFreeFunc freeFunc = memFunc<T>::Free){
            if(size == 0) return nil<T>();

            void * pt = manType::GetTree().insert(stack.top, size, sizeof(T), 1, allocFunc, freeFunc);
            stack.top = pt;
            return static_cast<T *>(pt);
        }

        // Stack Alloc 测试版本, 输入函数或者 lambda 表达始作为函数调用后的 callback
        template<typename T, typename C1, typename C2>
        static T * salloc(allocstack & stack, size_t size, const C1 & call_back1, const C2 & call_back2){
            if(size == 0) return nil<T>();

            using fn = memDebugFunc<T, C1, C2>;
            fn::C1() = &call_back1;
            fn::C2() = &call_back2;
            void * pt = manType::GetTree().insert(stack.top, size, sizeof(T), 1, fn::Alloc, fn::Free);
            stack.top = pt;
            return static_cast<T *>(pt);
        }

        // 更改计数器的值，值 +1
        template<typename T>
        static T * up(T * p){
            if(p != nullptr || p != nil<T>())
                PlusCount(manType::GetTree().find(static_cast<void *>(p)));
            return p;
        }

        static void * up(void * p){
            PlusCount(manType::GetTree().find(p));
            return p;
        }

        // 更改计数器的值，值 -1
        template<typename T>
        static void down(T * p){
            if(p == nullptr || p == nil<T>()) return ;
            MinusCount(manType::GetTree().find(static_cast<void *>(p)));
        }

        static void down(void * p){
            MinusCount(manType::GetTree().find(p));
        }

        // 释放内存
        // 因为加入了计数器，所以当计数器不是 <=0 的时候，我们不会释放内存
        // 直接在计数器上减一
        template<typename T>
        static void free(T * p){
            down(p);
        }

        static void free(void * p){
            down(p);
        }

        // 清空分配栈用的
        static void free(allocstack & stack){
            void * top = stack.top;
            while(top != nullptr){
                nodePtr np = manType::GetTree().find(top);
                if(np != nullptr){
                    top = np->mLast;
                    MinusCount(np);
                }else
                    top = nullptr;
            }
            stack.top = nullptr;
        }

        static std::ostream & print(std::ostream & os, const allocstack & stack){
            void * top = stack.top;
            while(top != nullptr){
                nodePtr np = manType::GetTree().find(top);
                if(np != nullptr){
                    os<<"["<<np->mValue<<", "<<np->mSize<<", "<<np->mLast<<", "<<np->mCount<<"]"<<std::endl;
                    top = np->mLast;
                }else
                    top = nullptr;
            }
            return os;
        }

        template<typename T>
        static void exchange(T *& p1,T *& p2){	    
            std::swap(p1,p2);
        }

        // 查看内存是否还存在，这里参数用的是指针
        // 注意函数除了判断分配的内存还有其成员或者数组内部的指针也会被判断
        template<typename T>
        static bool exist(T * p){
            return manType::GetTree().find(static_cast<void *>(p)) != nullptr;
        }

        // 打印树信息
        static void printTree(){
            manType::GetTree().print();
        }
    };

    allocstack::~allocstack(){
        memory::free(*this);
    }

    void allocstack::free(){
        memory::free(*this);
    }

    std::ostream & operator<<(std::ostream & os, const allocstack & stack){
        return memory::print(os, stack);
    }

    // 2020-4-6 暂时注释 shareMemory ，先统一使用上面的 memory 进行内存分配吧。
    // share memory 是专门使用共享内存块的
    // template<typename T, typename ManType = memMan>
    // class shareMemory{
    // public:
    //     using type = info_type_t<T>;
    // 	using ptr = info_ptr_t<T>;
    // 	using pptr = ptr*;
    //     using manType = info_type_t<ManType>;
    //     using memFn = memFunc<type>;
        
    //     template<typename C1, typename C2>
    //     using debugFn = memDebugFunc<type, C1, C2>;
        
    //     using treeType = typename manType::treeType;
    //     using nodePtr = typename manType::treeNodePtr;
        
    //     shareMemory() = delete;

    // public:
    //     // 2019-12-17 lambda 不能转换成普通的函数指针，放弃
    //     // alloc 测试版本, 输入函数或者 lambda 表达始作为函数调用后的 callback
    //     template<typename C1, typename C2>
    //     static ptr alloc(size_t size, const C1 & call_back1, const C2 & call_back2){
    //         if(size > 0){
    //             using fn = debugFn<C1, C2>;
    //             fn::C1() = &call_back1;
    //             fn::C2() = &call_back2;
    //             return static_cast<ptr>(manType::GetTree().insert(size, sizeof(type), 1, 0, fn::Alloc, fn::Free));
    //         }
    //         return nil<type>();
    //     }
        
    //     // alloc 测试版本, 可以自定义要进行申请内存块和删除内存块的函数
    //     // static ptr alloc(int size, memAllocFunc allocFunc, memFreeFunc freeFunc){
    //     //     if(size > 0){
    //     //         return static_cast<ptr>(manType::GetTree().insert(size, sizeof(type), 1, allocFunc, freeFunc));
	// 	// 	}
	// 	// 	return nil<type>();
	// 	// }

    //     // 整合，测试版本和非测试版本，上面的版本为使用 lambda 的回调版本
	// 	// 分配一个无 power 的指针，用计数器来计数
	// 	static ptr alloc(size_t size = 1, memAllocFunc allocFunc = memFn::Alloc, memFreeFunc freeFunc = memFn::Free){
	// 		if(size > 0){
    //             // std::cout<<"-------------"<<std::endl;
    //             // manType::GetTree().printTree();
    //             // ptr p = static_cast<ptr>(manType::GetTree().insert(size, sizeof(type), 1, 0, allocFunc, freeFunc));
    //             // std::cout<<"alloc = "<<(void *)p<<" size = "<<size<<std::endl;
    //             // manType::GetTree().printTree();
    //             // std::cout<<"-------------"<<std::endl;
    //             // return p;
    //             return static_cast<ptr>(manType::GetTree().insert(size, sizeof(type), 1, 0, allocFunc, freeFunc));
	// 		}
	// 		return nil<type>();
	// 	}

    //     template<typename MARK>
    //     static ptr malloc(const MARK & mark, size_t size, memAllocFunc allocFunc = memFn::Alloc, memFreeFunc freeFunc = memFn::Free){
    //         if(size > 0){
    //             return static_cast<ptr>(manType::GetTree().insert(size, sizeof(type), 0, mark.mark, allocFunc, freeFunc));
    //         }
    //         return nil<type>();
    //     }
        
	// 	// 直接在计数器减一即可
	// 	static void free(ptr p){
	// 		minusCount(p);
	// 	}

	// 	// 交换内存 并不影响计数器
	// 	static void exchange(ptr & p1,ptr & p2){
	// 		std::swap(p1,p2);
	// 	}

	// 	// 等于, 计数器 +1
	// 	static ptr assgin(ptr p){
	// 		plusCount(p);
	// 		return p;
	// 	}
		
	// 	// 查看内存是否还存在，这里参数用的是指针
	// 	// 注意函数除了判断分配的内存还有其成员或者数组内部的指针也会被判断
	// 	static bool exist(ptr p){
	// 		return manType::GetTree().find(static_cast<void *>(p)) != nullptr;
	// 	}
		
	// 	// 更改计数器的值，值 +1
	// 	static void plusCount(ptr p){
	// 		if(p == nullptr || p == nil<type>()) return ;
            
	// 		nodePtr np = manType::GetTree().find(static_cast<void *>(p));
	// 		if(np != nullptr){
    //             np->plusCount();
	// 		}
	// 	}

	// 	// 更改计数器的值，值 -1
	// 	static void minusCount(ptr p){
	// 		if(p == nullptr || p == nil<type>()) return ;
    //         nodePtr np = manType::GetTree().find(static_cast<void *>(p));
    //         // std::cout<<"minusCount np "<<(void *)np<<",p "<<(void *)p<<std::endl;
    //         if(np != nullptr){
    //             np->minusCount();
    //             if(np->mCount == 0){
    //                 manType::GetTree().erase(np->mValue);
    //             }
    //         }            
    //         // manType::ShowTree();
    //     }

    //     // 相同作用只是别名
    //     // 更改计数器的值，值 +1
	// 	static void down(ptr p){
    //         minusCount(p);
	// 	}

	// 	// 更改计数器的值，值 -1
	// 	static void up(ptr p){
    //         plusCount(p);
    //     }

    //     // 打印树信息
    //     static void printTree(){
    //         manType::GetTree().print();
    //     }
    // };
}

#endif
